/**
 * JAVACC DEMO 1.0
 * @copy right dwusoft company All rights reserved. 
 * @Package com.apache.passport.controller  
 */
package com.apache.passport.controller;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.owasp.esapi.ESAPI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.apache.api.manager.BaseManager;
import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.api.vo.ResultMsg;
import com.apache.cache.util.Validator;
import com.apache.database.constant.SystemTools;
import com.apache.passport.aop.LoginAopRunable;
import com.apache.passport.aop.PassportTheardPool;
import com.apache.passport.common.DesUtils;
import com.apache.passport.common.PassportHelper;
import com.apache.passport.entity.LoginInfo;
import com.apache.passport.entity.LonErrToken;
import com.apache.passport.entity.Token;
import com.apache.passport.entity.UctUser;
import com.apache.passport.manager.UctUserManager;

/**
 * description:登录登出操作  
 * @author Hou Dayu 创建时间：2014-12-18  
 * @Copyright(c)2014:
 */
@Controller
@RequestMapping({ "/passport/login/" })
public class LoginAction extends SsoBaseAction<UctUser> {

	@Autowired
	private UctUserManager uctUserManager;

	private final String LOGIN_SUCCESS = getPrefix() + "success";
	private final String LOGIN_REQUEST = getPrefix() + "request";
	private String COOKIENAME = SystemTools.getInstance().getValue("cookieName");

	@RequestMapping(value = "login", method = RequestMethod.POST)
	@ResponseBody
	public Object customLogin(HttpServletRequest request, HttpServletResponse response) {
		String userEname = request.getParameter("userName");
		String password = request.getParameter("password");
		String referer = request.getHeader("Referer"); //REFRESH  
		ResultMsg rmsg = new ResultMsg("F", "用户名不存在或密码错误");
		if (Validator.isNull(userEname)) {
			rmsg.setMsg("用户名不能为空");
			return rmsg;
		}
		if (Validator.isNull(password)) {
			rmsg.setMsg("密码不能为空");
			return rmsg;
		}
		return null;
	}

	/**
	 * TODO 登录.  
	 * @see 
	 */
	@RequestMapping({ "login.action" })
	@ResponseBody
	public Object login(HttpServletRequest request, HttpServletResponse response, UctUser user) {
		ResultEntity result = new ResultEntity();
		//判断是否为外部系统登录
		String sysEname = request.getParameter("sys");
		String setCookieUrl = request.getParameter("cset");
		String goUrl = request.getParameter("go");
		String clientId = request.getParameter("_client");
		String tokenCookie = PassportHelper.getInstance().getCurrCookie(request);
		Token tokenc = (Token) SystemTools.getInstance().getCache("loginToken").getCacheCloneByKey(tokenCookie);
		String goOn = SystemTools.getInstance().getValue("otherGO");
		String tokenId = Validator.generate() + request.getSession().getId();
		String service_url = SystemTools.getInstance().getValue("rpc_service_url");
		ResultMsg rmsg = new ResultMsg("F", "用户名不存在或密码错误");

		//如果为没有go地址,则自动赋值,防止其他项目无法登陆
		if (Validator.isNull(goUrl)) {
			goUrl = SystemTools.getInstance().getValue("login.url");
			goUrl += SystemTools.getInstance().getValue("jump.url");
		}

		boolean flag_op = false;
		if (Validator.isNull(user.getUserEname())) {
			rmsg.setMsg("用户名不能为空");
			return rmsg;
		}
		if (Validator.isNull(user.getUserPass())) {
			rmsg.setMsg("密码不能为空");
			return rmsg;
		}
		if (Validator.isNull(sysEname)) {
			sysEname = "passport";
		}
		if (goOn.equals(sysEname)) {
			flag_op = true;
			sysEname = "移动设备或非验证系统";
		}

		//LoggerVo logvo = getLoggerVo("用户登录", "用户[" + user.getUserEname() + "]登录", "", "", "passport");
		LoginInfo loginInfo = getLoginInfo(request, sysEname, "", sysEname, user.getUserEname(), tokenId);
		ParamsVo<UctUser> vo = this.getParamsVo(request, null);

		if (!Validator.isNull(sysEname) && !Validator.isNull(setCookieUrl) && !Validator.isNull(goUrl)
				&& !Validator.isNull(clientId)) {
			//2015年5月6日15:42:31
			//防止出现恶意XSS脚本攻击
			setCookieUrl = ESAPI.encoder().decodeForHTML(setCookieUrl);
			goUrl = ESAPI.encoder().decodeForHTML(goUrl);
			clientId = ESAPI.encoder().decodeForHTML(clientId);
			sysEname = ESAPI.encoder().decodeForHTML(sysEname);

			boolean csetDomain = PassportHelper.getInstance().isDomain(setCookieUrl);
			//boolean goDomain = PassportHelper.getInstance().isDomain(goUrl);
			//if (!csetDomain || !goDomain) {
			if (!csetDomain) {
				rmsg.setMsg("URL地址信息错误!");
				return rmsg;
			}

			//2015年2月2日09:16:36 增加sha1解密
			ArrayList<String> lst = new ArrayList<String>();
			lst.add(service_url);
			if (flag_op) {
				lst.add(goOn);
			} else {
				lst.add(sysEname);
			}
			lst.add(setCookieUrl);
			lst.add(goUrl);
			lst.add("apache");
			Collections.sort(lst);
			String sha1Rtn = PassportHelper.getInstance().SHA1(lst);
			if (!sha1Rtn.equals(clientId)) {
				rmsg.setFlag("F");
				rmsg.setMsg("系统检测到URL信息被篡改!");
				return rmsg;
			}

			if (!Validator.isEmpty(tokenc)) {
				rmsg.setFlag("T");
				rmsg.setMsg("跳转页面");
				return rmsg;
			} else {
				ParamsVo userStateVo = new ParamsVo();
				userStateVo.setMethodKey("userState");
				userStateVo.setParams("userEname", user.getUserEname());
				result = (ResultEntity) uctUserManager.execute(userStateVo);
				if ("F".equals(result.getEntity())) {
					rmsg.setFlag("F");
					rmsg.setMsg(result.getMessage());
					return rmsg;
				}

				String remoteIp = request.getRemoteAddr();
				vo.setMethodKey("outSideLogin");
				vo.setObj(user);
				vo.setParams("loginInfo", loginInfo);
				vo.setParams("remoteIp", remoteIp);
				vo.setParams("sessionId", request.getSession().getId());
				vo.setParams("tokenId", tokenId);
				vo.setParams("userEname", user.getUserEname());
				//vo.setParams("userPass", MD5Utils.MD5(user.getUserPass()));
				//2015年1月30日16:06:45 update 去掉md5加密 前端页面 index.jsp添加md5加密
				vo.setParams("userPass", user.getUserPass());
				vo.setParams("sysEname", sysEname);
				vo.setParams("setCookieUrl", setCookieUrl);
				vo.setParams("goUrl", goUrl);
				vo.setParams("clientId", clientId);
				boolean flag = (Boolean) uctUserManager.execute(vo);
				if (flag) {
					request.setAttribute("tokenId", tokenId);
					Cookie cookie = new Cookie(COOKIENAME, tokenId);
					cookie.setPath("/");
					response.addCookie(cookie);

					Cookie ucsso = new Cookie("_uc.sso", DesUtils.getInstance().encrypt(user.getUserEname()));
					ucsso.setPath("/");
					response.addCookie(ucsso);

					rmsg.setFlag("T");
					//2015年6月8日16:40:07 修改| 替换
					goUrl = goUrl.replace("|", "&");
					savelogInfo(loginInfo);
					rmsg.setMsg(goUrl);
					return rmsg;
				} else {
					rmsg = checkErrorToken(remoteIp, user, rmsg, request);
				}
			}
		} else {

			ParamsVo userStateVo = new ParamsVo();
			userStateVo.setMethodKey("userState");
			userStateVo.setParams("userEname", user.getUserEname());
			result = (ResultEntity) uctUserManager.execute(userStateVo);
			if ("F".equals(result.getEntity())) {
				rmsg.setFlag("F");
				rmsg.setMsg(result.getMessage());
				return rmsg;
			}

			String remoteIp = request.getRemoteAddr();
			//非外部系统连接登录
			vo.setMethodKey("login");
			vo.setObj(user);

			vo.setParams("loginInfo", loginInfo);
			vo.setParams("remoteIp", remoteIp);
			vo.setParams("sessionId", request.getSession().getId());
			vo.setParams("tokenId", tokenId);
			vo.setParams("userEname", user.getUserEname());
			//vo.setParams("userPass", MD5Utils.MD5(user.getUserPass()));
			//2015年1月30日16:06:45 update 去掉md5加密 前端页面 index.jsp添加md5加密
			vo.setParams("userPass", user.getUserPass());
			boolean flag = (Boolean) uctUserManager.execute(vo);
			if (flag) {
				rmsg.setFlag("T");
				//2015年6月8日16:40:07 修改| 替换
				goUrl = goUrl.replace("|", "&");
				rmsg.setMsg(goUrl);
				Cookie cookie = new Cookie(COOKIENAME, tokenId);
				cookie.setPath("/");
				response.addCookie(cookie);

				Cookie ucsso = new Cookie("_uc.sso", DesUtils.getInstance().encrypt(user.getUserEname()));
				ucsso.setPath("/");
				response.addCookie(ucsso);

				request.getSession().setAttribute("goUrl", "/");
				savelogInfo(loginInfo);
				return rmsg;
			} else {
				rmsg = checkErrorToken(remoteIp, user, rmsg, request);
			}
		}

		return rmsg;
	}

	private ResultMsg checkErrorToken(String remoteIp, UctUser user, ResultMsg rmsg, HttpServletRequest request) {
		//插件中存了错误次数,则在此判断
		LonErrToken token = (LonErrToken) SystemTools.getInstance().getCache("loginErrToken")
				.getCacheCloneByKey(remoteIp + user.getUserEname());
		if (!Validator.isEmpty(token)) {
			String errCount = token.getLoginCount();
			String mim = token.getMim();
			int count = Integer.parseInt(errCount);
			String[] params = { mim };
			if (3 == count) {
				rmsg.setMsg(PassportHelper.getInstance().getMessage(request, "login_err_3", params, ""));
			} else if (6 == count) {
				rmsg.setMsg(PassportHelper.getInstance().getMessage(request, "login_err_6", params, ""));
			} else if (9 == count) {
				rmsg.setMsg(PassportHelper.getInstance().getMessage(request, "login_err_9", params, ""));
			} else if (12 == count) {
				rmsg.setMsg(PassportHelper.getInstance().getMessage(request, "login_err_12", params, ""));
			}
		}
		return rmsg;
	}

	@RequestMapping("/outside.action")
	public String mode(HttpServletRequest request) throws Exception {
		String goUrl = request.getParameter("go");
		return "redirect:" + goUrl;
	}

	/**
	 * description: 封装信息对象 
	 * @param request
	 * @param lastSysEname 最后登录系统
	 * @param lastSysTime 最后登录系统时间
	 * @param sysEname 当前登录系统名称
	 * @param userEname 当前登录人
	 * @return  
	 * @author Hou Dayu 
	 * @update 2014-12-19
	 */
	private LoginInfo getLoginInfo(HttpServletRequest request, String lastSysEname, String lastSysTime,
			String sysEname, String userEname, String tokenId) {
		String lgnLastipaddress = PassportHelper.getInstance().getIpAddr(request);
		String header = request.getHeader("User-agent");
		String lgnLastdevice = "";
		if (!Validator.isNull(header)) {
			int beginIndex = header.indexOf("(") + 1;
			int endIndex = header.indexOf(")");
			lgnLastdevice = header.substring(beginIndex, endIndex);
		}
		LoginInfo loginInfo = new LoginInfo();

		loginInfo.setTokenId(tokenId);
		loginInfo.setSessionId(request.getSession().getId());
		loginInfo.setSysEname(sysEname);//当前登录系统
		loginInfo.setUserEname(userEname);//当前登录人
		if (lgnLastdevice.contains("iPhone") || lgnLastdevice.contains("iPad") || lgnLastdevice.contains("iPad")
				|| lgnLastdevice.contains("iTouch") || lgnLastdevice.contains("Mac")) {
			loginInfo.setLgnJudge("Apple");//品牌
		} else if (lgnLastdevice.contains("Android")) {
			loginInfo.setLgnJudge("Android");//品牌
		} else if (lgnLastdevice.contains("SymbianOS")) {
			loginInfo.setLgnJudge("SymbianOS");//品牌
		} else if (lgnLastdevice.contains("Windows")) {
			loginInfo.setLgnJudge("Windows");//品牌
		} else {
			loginInfo.setLgnJudge("未知品牌");//品牌
		}
		loginInfo.setLgnLastarea("未知地域");//地域
		loginInfo.setLgnLastdevice(lgnLastdevice);//介质
		loginInfo.setLgnLastipaddress(lgnLastipaddress);//ip地址
		if (Validator.isNull(lastSysEname)) {
			lastSysEname = "未知系统";
		}
		loginInfo.setLgnLastsys(lastSysEname);//最后登录系统
		if (Validator.isNull(lastSysTime)) {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			lastSysTime = sdf.format(new Date());
		}
		loginInfo.setLgnLasttime(lastSysTime);//最后登录时间
		return loginInfo;
	}

	/**
	 * description:  跳转至登录成功界面
	 * @param request
	 * @return  
	 * @author Hou Dayu 
	 * @update 2014-12-23
	 */
	@RequestMapping({ "login-success.action" })
	public ModelAndView initList(HttpServletRequest request) {
		ModelAndView view = new ModelAndView(LOGIN_SUCCESS);
		return view;
	}

	/**
	 * description:  跳转成定向
	 * @param request
	 * @return  
	 * @author Hou Dayu 
	 * @update 2014-12-31
	 */
	@RequestMapping({ "login-request.action" })
	public ModelAndView request(HttpServletRequest request) {
		ModelAndView view = new ModelAndView(LOGIN_REQUEST);
		return view;
	}

	private void savelogInfo(LoginInfo log) {
		LoginAopRunable runnable = new LoginAopRunable(log, "login");
		PassportTheardPool.getInstance().saveLogger(runnable);
	}

	@Override
	protected BaseManager<UctUser> getBaseManager() {

		return null;
	}

	@Override
	protected String getPrefix() {
		return "/passport/passport-";//passport-success.jsp
	}

	@Override
	protected Object data(HttpServletRequest httpservletrequest, String s, String s1) {

		return null;
	}

}
